import datetime
import time
import traceback

import cv2
import numpy as np
import logging
from AppConfig import *
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import QDialog, QWidget, QLabel, \
    QPushButton, QVBoxLayout, QHBoxLayout, QApplication, \
    QDialogButtonBox, QLineEdit, QMessageBox

"""保存dialog
"""


class SaveDialog(QDialog):

    def __init__(self, parent=None, mat: np.ndarray = None):
        super().__init__(parent)

        self.mat = mat

        # basic
        self.setWindowTitle("编辑保存信息")
        QBtn = QDialogButtonBox.Ok | QDialogButtonBox.Cancel
        self.buttonBox = QDialogButtonBox(QBtn)

        self.buttonBox.accepted.connect(self.save_to_disk)
        self.buttonBox.rejected.connect(self.reject)

        # layout
        self.layout = QVBoxLayout()

        # patient name
        name_layout = QHBoxLayout()
        self.patient_name = QLineEdit()
        name_layout.addWidget(QLabel("患者信息"))
        name_layout.addWidget(self.patient_name)

        time_layout = QHBoxLayout()
        self.patient_time = QLabel(datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"))
        time_layout.addWidget(QLabel("拍摄时间"))
        time_layout.addWidget(self.patient_time)

        # confirm
        self.layout.addLayout(name_layout)
        self.layout.addLayout(time_layout)
        self.layout.addWidget(self.buttonBox)
        self.setLayout(self.layout)

    def save_to_disk(self):
        if self.mat is None or self.patient_name.text().replace(" ", "") == "":
            QMessageBox.critical(None, "异常", "图像捕获失败，或者姓名为空")
        else:
            p_name = self.patient_name.text().replace(" ", "")
            p_t = self.patient_time.text()
            save_path = os.path.join(AppConfig.CACHE_PATH, "{}-{}.png".format(p_name, p_t))
            cv2.imwrite(save_path, self.mat)
            QMessageBox.information(None, "成功", "保存路径:{}".format(save_path))

        self.accept()


class CameraViewer(QWidget):
    def __init__(self):
        super().__init__()
        self.capture = None
        self.setup_ui()

        self.photo_click = False
        self.now_frame = None

    def setup_ui(self):
        # windows
        self.setWindowTitle("Camera Viewer")
        self.resize(WIN_WIDTH, WIN_HEIGHT)

        # imageview
        self.image_label = QLabel(self)
        self.image_label.setMinimumSize(WIN_WIDTH, WIN_HEIGHT)
        self.image_label.setAlignment(Qt.AlignCenter)

        # read capture
        self.start_button = QPushButton("读取相机", self)
        self.start_button.clicked.connect(self.start_capture)

        # save capture
        self.save_button = QPushButton("拍照")
        self.save_button.clicked.connect(self.snap_capture)

        # layout
        # cap image
        main_layout = QVBoxLayout()
        main_layout.addWidget(self.image_label)

        # button layout
        button_layout = QHBoxLayout()
        button_layout.addWidget(self.start_button)
        button_layout.addWidget(self.save_button)
        main_layout.addLayout(button_layout)

        self.setLayout(main_layout)

    @Slot()
    def start_capture(self):
        self.capture = cv2.VideoCapture(CAP_INDEX)
        self.capture.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc('M', 'J', 'P', 'G'))
        self.capture.set(cv2.CAP_PROP_AUTOFOCUS, CAP_AUTO_FOCUS)
        self.capture.set(cv2.CAP_PROP_FRAME_WIDTH, CAP_WIDTH)
        self.capture.set(cv2.CAP_PROP_FRAME_HEIGHT, CAP_HEIGHT)
        self.capture.set(cv2.CAP_PROP_FPS, CAP_FPS)

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.display_frame)
        self.timer.start(CAP_TIME)

    @Slot()
    def snap_capture(self):
        self.photo_click = True

        QTimer.singleShot(CAP_TIME, self.show_save_dialog)

    def show_save_dialog(self):
        save_dialog = SaveDialog(None, self.now_frame)
        save_dialog.show()
        save_dialog.exec()

    def display_frame(self):
        # time_start = time.perf_counter()
        try:
            ret, frame = self.capture.read()

            if ret:
                # read
                frame = cv2.resize(frame, (WIN_WIDTH, WIN_HEIGHT))

                # save
                if self.photo_click:
                    self.now_frame = frame.copy()
                    self.photo_click = False

                # mask
                h, w, ch = frame.shape
                mask = np.zeros_like(frame)
                cv2.circle(mask, (w // 2, h // 2), h // 2, (255, 255, 255), -1)

                # add weight
                frame = cv2.addWeighted(frame, 0.7, mask, 0.3, 0.0)

                # to qt
                frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                img = QImage(frame.data, w, h, ch * w, QImage.Format_RGB888)
                self.image_label.setPixmap(QPixmap.fromImage(img))
        except Exception as e:
            QMessageBox.critical(None, "异常", "相机读取异常，程序结束")
            logging.critical(traceback.format_exc())
            exit(-1)


if __name__ == "__main__":
    app = QApplication()
    viewer = CameraViewer()
    viewer.show()
    app.exec()
